local skynet = require "skynet"
local cluster = require "skynet.cluster"
local filelog = require "filelog"
local filename = "loginnodesocket.lua"

local configdao = require "configdao"
local timetool = require "timetool"
local md5 = require "md5"

local service = nil
local LoginnodeSocket = {
	service = nil
}

local platform2login_key = nil

function LoginnodeSocket.process(session, source, event, ...)
	-- 确定只进行一次赋值
	if not service then
		service = LoginnodeSocket.service
		platform2login_key = configdao.get_cfgsvrs_key("platform2login_key")
	end
	
	local f = LoginnodeSocket[event] 
	if f == nil then
		filelog.sys_error(filename.." LoginnodeSocket.process invalid event:"..event)
		return nil
	end
	skynet.retpack(f(...))
end

function LoginnodeSocket.open(fd, ip)
	service.tcpmng.open_socket(fd, ip)
end

function LoginnodeSocket.close(fd)
	service.tcpmng.close_socket(fd)
end

function LoginnodeSocket.error(fd, msg)
	service.tcpmng.close_socket(fd)
end

function LoginnodeSocket.warning(fd, size)
	-- size K bytes havn't send out in fd
	filelog.sys_warning("LoginsvrSocket warning:"..size.." K bytes havn't send out in "..fd)
end

--[[
// 只有一个协议。登录服，短连接，不需要握手，直接就发登录消息了。 
// 平台服生成 的 logintoken = md5(uid + tokentime + platform2login_key ）+ tokentime
// platform2login_key  是平台服和loginnode约定的（川乐里面已经变成客户端和loginnode的约定了）
// 三个可能接口：authwx, authuser, authguest
]]
function LoginnodeSocket.data(fd, msg, sz, realip)
	local msghead, msgbody = service.decode.c2sunpack(service.protobuf, msg)
    if not msghead or not msgbody then
        service.tcpmng.close_socket(fd)
        return
    end
    
    --获取ip
    local ip = nil
    if (msghead.msgname == "authwx" or msghead.msgname == "authuser") and msgbody.reportip ~= "" then
        ip = msgbody.reportip
    end
    ip = ip or realip or ""
    if ip == "" and service.tcpmng.connections[fd] then
        ip = service.tcpmng.connections[fd].ipport or ""
        ip = string.match(ip, "(.+):") or ""
    end

    --修改手机密码或获取验证码
    if msghead and (msghead.msgname == "changephonepassword" or msghead.msgname == "getverificationcode") then
        local respmsg = msghead.msgname .. "R"
        local result = skynet.call(".mainnode", "lua", msghead.msgname, msgbody, ip)
        if result then
            local retcode, retstr, msgbody = 0, "", {}
			if result.retcode then
				retcode = tonumber(result.retcode)
				retstr = result.retstr or ""
				msgbody = result.msgbody or {}
			else
				msgbody = result
			end
            service:send_resmsgto_client(fd, respmsg, msgbody, retcode, retstr)
        else
            service:send_resmsgto_client(fd, respmsg, _, -1, "system error")
            service.tcpmng.close_socket(fd)
        end
        return
    end

	if msghead == nil or (msghead.msgname ~= "authwx" and msghead.msgname ~= "authother" 
    and msghead.msgname ~= "authuser" and msghead.msgname ~= "authguest") then
		-- resmsg.result = "error"
		service:send_resmsgto_client(fd, "authR", _, 1, "must be auth msg")
		service.tcpmng.close_socket(fd)
		return
	end	
	-- 验证判断客户端 过来的token,通过后，通过create_session 给agent处理
	-- todo，是否验证token生成时间
	local tokentime = string.sub(msgbody.logintoken, 33)
	local newtoken = md5.sumhexa(msgbody.username .. tokentime .. platform2login_key ) .. tokentime
	if(newtoken ~= msgbody.logintoken) then
		service:send_resmsgto_client(fd, "authR", nil, 2, "erro:1, logintoken error")
		service.tcpmng.close_socket(fd)
		return
	end

    --检测ip
    local status, result = skynet.pcall(cluster.call, "datanode", ".router", "check_is_newuser", msghead.msgname, msgbody.username)
    if status and result then
        if ip == "" or not service:check_locationinfo(ip) then
            service:send_resmsgto_client(fd, "authR", nil, 3, "该地区暂未开放，敬请期待!")
		    service.tcpmng.close_socket(fd)
            return
        elseif service:check_limit_ip(ip) then
            service:send_resmsgto_client(fd, "authR", nil, 4, "登录过于频繁，请稍后重试!")
		    service.tcpmng.close_socket(fd)
            return
        end
    end

    --检测是否账号被冻结
    if service:check_limit_users(msgbody.username) then
        service:send_resmsgto_client(fd, "authR", nil, 5, "尝试次数过多，账号已冻结，请修改密码!")
	    service.tcpmng.close_socket(fd)
        return
    elseif msghead.msgname == "authuser" and msgbody.verification_code and msgbody.verification_code ~= "" then
        local result = service:check_ver_code(msgbody.username, msgbody.verification_code)
        if result.retcode ~= nil then
            service:send_resmsgto_client(fd, "authR", nil, result.retcode, result.retstr)
	        service.tcpmng.close_socket(fd)
            return
        end
    end

	service.tcpmng.create_session(fd, msghead.msgname, msgbody, realip)
end

return LoginnodeSocket